package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.*;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.BaseCategoryService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.common.config.pool.ServiceThreadPoolConfig;
import com.atguigu.tingshu.common.constant.RabbitConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.search.client.SearchFeignClient;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.awt.font.TextHitInfo;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    @Autowired
    private AlbumInfoMapper albumInfoMapper;
    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;
    @Autowired
    private AlbumStatMapper albumStatMapper;
    @Autowired
    private TrackInfoMapper trackInfoMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private BaseCategory3Mapper baseCategory3Mapper;
    @Autowired
    private BaseCategoryService baseCategoryService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    @Lazy
    private AlbumInfoService albumInfoService;

    // 保存专辑信息
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveAlbumInfo(AlbumInfoVo albumInfoVo) {
        // 1. 保存专辑的基本信息
        AlbumInfo albumInfo = new AlbumInfo();
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        // 设置用户id
        albumInfo.setUserId(AuthContextHolder.getUserId());
        // 设置专辑中声音的数量  新创建的数量为 0
        albumInfo.setIncludeTrackCount(0);
        // 判断收费类型 如果不是免费则设置试听集数和时长
        if (!albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)) {
            albumInfo.setTracksForFree(5);
            albumInfo.setSecondsForFree(60);
        }
        // 设置专辑的状态 设置为通过  实际开发设置为未通过
        albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
        // 查询专辑属性值 判断是否完结
        albumInfo.setIsFinished(0); // 默认未完结
        List<AlbumAttributeValueVo> attributeList = albumInfoVo.getAlbumAttributeValueVoList();
        if (!CollectionUtils.isEmpty(attributeList)) {
            for (AlbumAttributeValueVo albumAttributeValueVo : attributeList) {
                if (albumAttributeValueVo.getValueId().equals(SystemConstant.ALBUM_ATTRIBUTE_IS_FINISHED)) {
                    albumInfo.setIsFinished(1);
                    break;
                }
            }
        }
        // 保存 并自动返回id
        albumInfoMapper.insert(albumInfo);
        // 2. 保存专辑的属性信息
        attributeList.forEach(attribute -> {
            AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
            albumAttributeValue.setAlbumId(albumInfo.getId());
            albumAttributeValue.setAttributeId(attribute.getAttributeId());
            albumAttributeValue.setValueId(attribute.getValueId());
            albumAttributeValueMapper.insert(albumAttributeValue);
        });

        // 3. 保存专辑的统计信息
        insertAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_BROWSE);// 浏览量
        insertAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_COMMENT);// 评论数
        insertAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_PLAY);// 播放量
        insertAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_SUBSCRIBE);// 订阅量
        //
        // 如果专辑为open则创建时候将专辑导入到es
        if (albumInfo.getIsOpen().equals(SystemConstant.ALBUM_IS_OPEN) &&
                albumInfo.getStatus().equals(SystemConstant.ALBUM_STATUS_PASS)
        ) {
            String unique = UUID.randomUUID().toString().replace("-", "");
            String uniqueAlbumId = unique + "-" + albumInfo.getId();
            rabbitTemplate.convertAndSend(RabbitConstant.ALBUM_EXCHANGE, RabbitConstant.ALBUM_UPPER_RK, uniqueAlbumId);
        }
    }


    private void insertAlbumStat(Long albumId, String statType) {
        AlbumStat albumStat = new AlbumStat();
        albumStat.setStatType(statType);// 播放量 // 类型
        albumStat.setAlbumId(albumId);
        albumStat.setStatNum(0);// 数目
        albumStatMapper.insert(albumStat);
    }

    // 获取用户专辑分页列表
    // 查询时传递参数封装到 AlbumInfoQuery 实体类中。
    //查看数据应该看到专辑列表同时包含专辑的【播放量，评论数，购买数，订阅量】
    @Override
    public Page<AlbumListVo> findUserAlbumPage(Long pageNum, Long pageSize, AlbumInfoQuery albumInfoQuery) {

        // 获取用户id
        Long userId = AuthContextHolder.getUserId();
        // 设置用户id到查询参数
        albumInfoQuery.setUserId(userId);
        // 调用mapper方法 mybatis-plus的分页查询只需要将分页参数传递给mapper方法即可+分页插件 会自动拼接分页sql分页
        return albumInfoMapper.findUserAlbumPage(new Page<>(pageNum, pageSize), albumInfoQuery);
    }

    @Transactional(rollbackFor = Exception.class)
    // 删除专辑信息根据id
    @Override
    public void removeAlbumInfoById(Long id) {
        // 1. 如果专辑下面有声音则不能删除
        long count = trackInfoMapper.selectCount(new LambdaUpdateWrapper<TrackInfo>().eq(TrackInfo::getAlbumId, id));
        if (count > 0) {
            throw new GuiguException(ResultCodeEnum.ALBUM_TRACK_NOT_EMPTY);
        }
        albumInfoMapper.deleteById(id);
        // 2. 删除专辑的属性信息
        albumAttributeValueMapper.delete(new LambdaUpdateWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));
        // 3. 删除专辑的统计信息
        albumStatMapper.delete(new LambdaUpdateWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, id));
        // 4. 下架专辑
        String unique = UUID.randomUUID().toString().replace("-", "");
        String uniqueAlbumId = unique + "-" + id;
        rabbitTemplate.convertAndSend(RabbitConstant.ALBUM_EXCHANGE, RabbitConstant.ALBUM_DOWN_RK, uniqueAlbumId);
    }

    // 根据id查询专辑信息
    @Override
    public AlbumInfoVo getAlbumInfoById(Long id) {
        AlbumInfoVo albumInfoVo = new AlbumInfoVo();
        AlbumInfo albumInfo = albumInfoMapper.selectById(id);
        BeanUtils.copyProperties(albumInfo, albumInfoVo);
        // 查询专辑属性值
        List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper
                .selectList(new LambdaUpdateWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumAttributeValueList.stream().map(albumAttributeValue -> {
            AlbumAttributeValueVo albumAttributeValueVo = new AlbumAttributeValueVo();
            BeanUtils.copyProperties(albumAttributeValue, albumAttributeValueVo);
            return albumAttributeValueVo;
        }).toList();
        albumInfoVo.setAlbumAttributeValueVoList(albumAttributeValueVoList);
        return albumInfoVo;
    }

    // 修改专辑信息通过专辑id
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateAlbumInfo(Long id, AlbumInfoVo albumInfoVo) {

        // todo 为了保证数据的一致性可以采用延迟双删除 或者  maxwell
        // 1. 修改数据前删除缓存
        // album:cache:[1100]
        String cacheKey = "album:cache:[" + id + "]";
        redisTemplate.delete(cacheKey);


        AlbumInfo albumInfo = new AlbumInfo();
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        albumInfo.setId(id);
        albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
        // 1. 修改专辑基本信息
        albumInfoMapper.updateById(albumInfo);
        // 2. 清除属性信息
        albumAttributeValueMapper.delete(new LambdaUpdateWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        // 插入属性信息
        albumAttributeValueVoList.forEach(albumAttributeValueVo -> {
            AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
            BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
            albumAttributeValue.setAlbumId(id);
            albumAttributeValueMapper.insert(albumAttributeValue);
        });

        // 3. 更新专辑信息 将新的数据同步到es中
        // 如果专辑为open并且审核通过的则创建时候将专辑导入到es 直接根据文档id覆盖了
        // 从不公开--->公开 需要上架
        // 从公开--->不公开 需要下架
        if (albumInfo.getIsOpen().equals(SystemConstant.ALBUM_IS_OPEN) &&
                albumInfo.getStatus().equals(SystemConstant.ALBUM_STATUS_PASS)
        ) {
            String unique = UUID.randomUUID().toString().replace("-", "");
            String uniqueAlbumId = unique + "-" + id;
            rabbitTemplate.convertAndSend(RabbitConstant.ALBUM_EXCHANGE, RabbitConstant.ALBUM_UPPER_RK, uniqueAlbumId);
        } else if (albumInfo.getIsOpen().equals(SystemConstant.ALBUM_IS_NOT_OPEN) ||
                albumInfo.getStatus().equals(SystemConstant.ALBUM_STATUS_NO_PASS)
        ) {
            String unique = UUID.randomUUID().toString().replace("-", "");
            String uniqueAlbumId = unique + "-" + id;
            rabbitTemplate.convertAndSend(RabbitConstant.ALBUM_EXCHANGE, RabbitConstant.ALBUM_DOWN_RK, uniqueAlbumId);
        }
        // todo 更新完数据删除缓存 保证下次查询到的是最新的数据
        // 方式1 异步任务
//        ServiceThreadPoolConfig.getExecutor().execute(() -> {
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            log.info("延迟删除缓存");
//            redisTemplate.delete("album:cache:["+id+"]");
//        });
        // 方式2 异步方法 @Async
        albumInfoService.deleteCache(id);
    }

    @Async
    public void deleteCache(Long id) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("延迟删除缓存");
        redisTemplate.delete("album:cache:[" + id + "]");
    }

    // 获取用户所有专辑列表
    @Override
    public List<AlbumInfo> findUserAllAlbumList() {
        try {
            Long userId = AuthContextHolder.getUserId();

            List<AlbumInfo> albumInfoList = albumInfoMapper.selectList(
                    new LambdaQueryWrapper<AlbumInfo>()
                            // todo userId 不为空查询所有  后续还需要修改
                            .eq(AlbumInfo::getUserId, userId)
                            .select(AlbumInfo::getId, AlbumInfo::getAlbumTitle) // 指定查询的列
                            .orderByDesc(AlbumInfo::getId)    // 排序 最近添加的排在上面
            );
            return albumInfoList;
        } catch (Exception e) {
            throw new GuiguException(ResultCodeEnum.ALBUM_NOT_EXIST_ERROR);
        }
    }

    // 远程调用获取专辑首页分页列表
    @Override
    public Page<AlbumListVo> getAlbumInfoIndexPage(Long pageNum, Long pageSize) {
        // new AlbumInfoQuery() 默认为空，查询所有 防止sql中的query出现空指针
        Page<AlbumListVo> albumPage = albumInfoMapper.findUserAlbumPage(new Page<>(pageNum, pageSize), new AlbumInfoQuery());

        return albumPage;
    }

    // 根据专辑id获取专辑属性
    @Override
    public List<AttributeValueIndex> findAttributesByAlbumId(Long id) {
        // 需要查询attributeId 和 valueId
        // 需要查询 album_attribute_value 表
        List<AlbumAttributeValue> albumAttributeValuesList = albumAttributeValueMapper.selectList(new LambdaUpdateWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));
        List<AttributeValueIndex> attributeValueIndexList = albumAttributeValuesList.stream().map(
                albumAttributeValue -> {
                    AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                    BeanUtils.copyProperties(albumAttributeValue, attributeValueIndex);
                    return attributeValueIndex;
                }
        ).toList();
        return attributeValueIndexList;
    }

    @Override
    public AlbumListVo getAlbumListVoByAlbumId(Long id) {
        AlbumListVo albumListVo = albumInfoMapper.getAlbumListVoByAlbumId(id);
        return albumListVo;
    }

    @Override
    public AlbumStatVo getAlbumStatVo(Long id) {

        AlbumStatVo albumStatVo = albumStatMapper.selectByAlbumId(id);
        return albumStatVo;
    }
}
